using NL;
using NL.UI;
using System;
using UnityEngine;

namespace SinceTimes.NetWork
{
    public partial class Net : MonoBehaviour
    {
        [Header("是否将自己设计为单例")]
        public bool InstancedForSingle = true;

        [Header("服务器 地址, 端口")]
        public string Url;
        public ushort Port;
        public string PortList = "420;421";

        public string ServerIP
        {
            get
            {
               Uri uri = new Uri(Url);
                return uri.Host;
            }
        }

        public string SceneOnConnectOK="sc_connect";
        public string SceneOnConnectLOSS="sc_home";

        [Header("使用的TCP链接,UDP链接的 Peer预设.")]
        public GameObject Mod_Peer ;

        [Header("是否开启自动重连.")]
        public bool AutoReconnect = true;


        public float PeerHealthyDuration = 1f;
        public bool BadPeerDestroyable = true;

        [Header("心跳间隔")]
        public float BeatHeartDuration = 5;

        public long UserID= 288526694535397876;//576995939588244458

        public bool ShowLog = false;
        public bool ShowError = true;

        protected IPeer _NowPeer;

        public static Net INSTANCE=>_Instance;

        protected static Net _Instance;

        static float _DELAY;

        IHandler[] _Handlers;

        public Tiper Mod_LoadingTip;

        public static Tiper MOD_TIP_LOADING;
        public static bool SHOWLOG => _Instance==null?false: _Instance.ShowLog;
        public static bool SHOWERROR => _Instance == null ? true : _Instance.ShowError;
        protected virtual void Awake()
        {
            if (InstancedForSingle)
            {
                if (_Instance != null)
                    GameObject.Destroy(_Instance.gameObject);

                DontDestroyOnLoad(gameObject);
                _Instance = this;
            }
            if (Mod_Peer != null && Mod_Peer.activeInHierarchy)
                Mod_Peer.SetActive(false);

            _Handlers = GetComponentsInChildren<IHandler>();

            Reset();

            if (Mod_LoadingTip != null)
            {
                MOD_TIP_LOADING = Mod_LoadingTip;
            }

        }
        public void Reset()
        {
            __ReceivePool.Clear();
            __ResponsePool.Clear();
            __RequestePool.Clear();
            __SendPool.Clear();
            _NowPeer = null;
        }
        protected virtual void  Start()
        {

            LOG.Show(gameObject, () =>
            {
                return $"NET-LAG={ReponseDelayInMS} ms";
            });
           // _CreatePeer();
        }
        

        //public void _DoPeerConnectOk(IPeer _peer) 
        //{

        //    if(!string.IsNullOrEmpty(SceneOnConnectOK))
        //        SceneManager.LoadScene(SceneOnConnectOK, LoadSceneMode.Single);
        //}

        //public void _DoPeerConnectLose(IPeer _peer, string _err)
        //{
        //    if (!string.IsNullOrEmpty(SceneOnConnectLOSS))
        //        SceneManager.LoadScene(SceneOnConnectLOSS, LoadSceneMode.Single);
        //}

        protected virtual IPeer _CreatePeer(bool reconnect=false)
        {
            
            GameObject _newpeer = GameObject.Instantiate(Mod_Peer, transform);
            _newpeer.SetActive(true);
            IPeer peer= _newpeer.GetComponent<IPeer>();

            if(peer!=null)
            {
                if(!string.IsNullOrEmpty(Url))   peer.Url = Url;
                if(!string.IsNullOrEmpty(PortList))
                {
                    peer.PortList = PortList;
                }
                if(Port>0)  peer.Port = Port;

            }

            OnNewPeer(peer, reconnect);


            return peer.WaitUserAuth(OnPeerUserAuth)
                .WaitConnected(OnPeerConnected).WaitClosed(OnPeerClosed);
        }
        protected virtual void OnNewPeer(IPeer peer,bool reconnect)
        {
            try
            {
                _OnNewPeer?.Invoke(peer, reconnect);
            }
            catch
            {

            }
        }

        Action<IPeer, bool> _OnNewPeer;
        public void WaitNewPeer(Action<IPeer, bool> on)
        {
            _OnNewPeer = on;
        }
        public   IPeer NowPeer;


        
        protected virtual string OnPeerUserAuth(IPeer who, IPeerMessage msg)
        {
             return "";
        }
        protected virtual  void OnPeerConnected(IPeer peer)
        {
            NowPeer = peer;
            _ReconnectingCheckCount = 0;
            //UI.ShowTiper($"建立链接[{peer.Url}]");
            Debug.Log($"[Net.OnPeerConnected]:建立链接:[{peer.Url}]");
            _ONPeerConnected?.Invoke();
        }

        protected virtual void OnPeerClosed(IPeer peer)
        {
            Debug.Log($"[Net.OnPeerClosed]:连接已经断开[{peer.Url}...{Time.time}]");
            if (NowPeer==peer)
                NowPeer = null;
            //UI.ShowTiper($"连接已经断开[{peer.Url}]");
            _ONPeerCloseed?.Invoke();
        }

        //子线程...
        public void AddRecive(IPeerMessage msg)
        {
            //有等待返回的 进入 返回队列.
            if (msg == null) return;



            //if (_msg.Serial > 0 && _Requesters.ContainsKey(_msg.Serial))
             if(msg.MessageIndex > 0 && __RequestePool.ContainsKey(msg.MessageIndex))
                __ResponsePool.Enqueue(msg);
            else
                __ReceivePool.Enqueue(msg);

 
        }

        event  Action _ONPeerConnected;
        public Net WaitPeerConnect(Action on, GameObject binded)
        {
            _ONPeerConnected += on;

            if (binded != null)
            {
                binded.WAITDestroy(w =>
                {
                    _ONPeerConnected -= on;
                });
            }
            return this;
        }
        event Action _ONPeerCloseed;
        public Net WaitPeerClose(Action on, GameObject binded)
        {
            _ONPeerCloseed += on;

            if (binded != null)
            {
                binded.WAITDestroy(w =>
                {
                    _ONPeerCloseed -= on;
                });
            }
            return this;
        }


        public Net Connect(string url = "", ushort port = 0)
        {

            if (!string.IsNullOrEmpty(url)) _Instance.Url = url;
            if (port > 0) _Instance.Port = port;

            _CreatePeer();

            return this;
        }

        public static Net CONNECT(string url = "", ushort port = 0)
        {
            return _Instance.Connect(url, port);
        }

        //向服务端发送消息
        // 将消息添加到 发送池

        public void Send(IPeerMessage _msg)
        {
            
            __SendPool.Enqueue(_msg);


        }
        public static void SEND(IPeerMessage _msg)
        {
            _Instance?.Send(_msg);
        }

        /// <summary>
        /// 标记阻塞性请求
        /// </summary>
        /// <param name="blockIni"></param>
        protected virtual void MarkBlockRequest(UIBlockIni blockIni)
        {

        }
        /// <summary>
        /// 标记阻塞性请求响应
        /// </summary>
        /// <param name="blockIni"></param>
        protected virtual void MarkBlockBlockResponse(UIBlockIni blockIni)
        {

        }

        public bool AutoReRequestForTimeout = false;
        //向服务端请求
        //使用请求消息创建 请求等待...
        //
        public Requester Request<T>(IPeerMessage _msg, Action<T> _onresponse, UIBlockIni blockIni = null) where T : IPeerMessage
        {

            if (_msg == null) return null;

            Requester _responser = null;

            if (_msg.MessageIndex > 0)
            {
                // 创建 请求消息的 等待
                _responser = gameObject.ADDChild("Responer")
                    .AddComponent<Requester>().Set(_msg, blockIni)
                    .WaitStart(res => 
                    {
                        if (blockIni != null)
                            MarkBlockRequest(blockIni);
                    })
                    .Wait((w) => //等待返回..
                    {
                        if (blockIni != null)
                            MarkBlockBlockResponse(blockIni);


                        if (w.State == Requester.RequesterState.TimeOut)
                        {
                            OnRequestTimeOut(_msg);
                            // 如果是超时..并且允许自动重发.
                            if (AutoReRequestForTimeout )
                            {
                                LOG.Add($"ReRequestForTimeout : [type={_msg.MessageType}, index={_msg.MessageIndex}] => {_msg}");
                                Request<T>(_msg, _onresponse, blockIni);
                            }
                            return;
                        }


                        // 如果是超时..并且允许自动重发.
                        if (AutoReRequestForTimeout && w.State == Requester.RequesterState.TimeOut)
                        {
                            if (_msg != null)
                            {
                                LOG.Add($"ReRequestForTimeout : [type={_msg.MessageType}, index={_msg.MessageIndex}] => {_msg}");
                            }
                            Request<T>(_msg,_onresponse,blockIni);
                            return;
                        }

                        if (w == null)
                        {
                            OnRequestError(_msg);
                        }else
                        {
                            try
                            {
                                _onresponse?.Invoke((T)w.ResponseMessage);
                            }
                            catch (Exception e)
                            {
                                LOG.Add($"[Requester.Request<T>.Wait(w)]:_onresponse?.Invoke:Error={e}");
                            }
                        }
  
                       


                    });

                // 按照消息索引 添加监听字典...
                if (__RequestePool.ContainsKey(_msg.MessageIndex))
                    __RequestePool[_msg.MessageIndex] = _responser;
                else
                    __RequestePool.Add(_msg.MessageIndex, _responser);
            }

            Send(_msg);

            return _responser;
        }
        protected virtual void OnRequestTimeOut(IPeerMessage msg)
        {
            LOG.Add($"[Net.OnRequestTimeOut]:msg={msg.MessageIndex}");

        }
        protected virtual void OnRequestError(IPeerMessage msg)
        {
            LOG.Add($"[Net.OnRequestError]:msg={msg.MessageIndex}");

        }

        public static Requester REQUEST<T>(IPeerMessage _msg, Action<T> _onresponse, UIBlockIni blockIni = null) where T : IPeerMessage
        {
            return _Instance.Request<T>(_msg, _onresponse, blockIni);
        }
        /// <summary>
        /// 默认使用 ProtobufMsg 作为消息体结构
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_msg"></param>
        /// <param name="_onresponse"></param>
        public static Requester REQUEST(IPeerMessage _msg, Action<ProtobufMsg> _onresponse, UIBlockIni blockIni = null)
        {
            return REQUEST<ProtobufMsg>(_msg, _onresponse, blockIni);
        }
        public override string ToString()
        {
            return $"" ;
           
        }
        //   void IPeer.Request(IPeerMessage _msg, Action<IPeerMessage, IPeerMessage> _onresponse) => Request((T)_msg, _onresponse);


       
    }
}

